<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>贪吃蛇Vue版本</title>
    <link rel="stylesheet" href="./index.css" />
</head>

<body>
    <div class="web">
        <cell 
            v-for="(item,index) in snakeArr" 
            :class="gameStatus.isEnd ? 'endCell' : 'cell'" 
            :x="item.x"
            :y="item.y"
            :key="index">
        </cell>
        <div
            class="randomCell" 
            :style="{left: randomCellX * 10 + 'px',top: randomCellY * 10 + 'px'}">
        </div>
    </div>
    <script src="./vue-2.4.0.js"></script>
    <script>
        const MAX_X = 50; //最大行
        const MAX_Y = 50; //最大列

        const Cell = {
            props: ["x", "y"],
            template: `<div  :style="{left: x * 10 + 'px',top: y * 10 + 'px'}" ></div>`,
        };

        new Vue({
            el: ".web",
            data: {
                direction: "ArrowRight", // 移动的方向
                randomCellX: 0,
                randomCellY: 0,
                timer: null,
                // 游戏状态
                gameStatus: {
                    isEnd: false, //是否结束
                    pause: false, //是否暂停
                    pauseDirection: "ArrowRight", //暂停时移动的方向
                },
                snakeArr: [
                    {
                        x: 0,
                        y: 0,
                    },
                ],
            },
            methods: {
                move(x, y) {
                    let nextX = this.snakeArr[0].x + x;
                    let nextY = this.snakeArr[0].y + y;
                    // 游戏结束或者暂停时不能移动
                    if (this.gameStatus.isEnd || this.gameStatus.pause) {
                        return;
                    }
                    // 游戏结束
                    if (this.isGameOver(nextX, nextY)) {
                        this.gameOver();
                        return;
                    }
                    // 触碰到随机生成的方块
                    if (
                        nextX == this.randomCellX &&
                        nextY == this.randomCellY
                    ) {
                        let lastCellX = this.snakeArr[this.snakeArr.length - 1].x;
                        let lastCellY = this.snakeArr[this.snakeArr.length - 1].y;
                        this.snakeArr.push({ x: lastCellX, y: lastCellY });
                        this.twoRandomNum();
                    }
                    ////每一次移动都是往头部插入一个元素,然后将尾部的元素给删除
                    this.snakeArr.unshift({ x: nextX, y: nextY });
                    let last = this.snakeArr.pop();
                },
                // 生成随机坐标
                twoRandomNum() {
                    let x_y = this.snakeArr.map((item) => [item.x, item.y]);
                    let x = 0;
                    let y = 0;
                    let flag = false;
                    while (true) {
                        x = Math.floor(Math.random() * MAX_X);
                        y = Math.floor(Math.random() * MAX_Y);
                        for (let i = 0; i < x_y.length; i++) {
                            if (x_y[i][0] == x && x_y[i][1] == y) {
                                flag = false;
                                break;
                            } else {
                                flag = true;
                            }
                        }
                        if (flag) {
                            break;
                        }
                    }
                    this.randomCellX = x;
                    this.randomCellY = y;
                },
                isGameOver(x, y) {
                    // 触碰到边界
                    if (
                        (this.direction == "ArrowRight" && x == MAX_X) ||
                        (this.direction == "ArrowLeft" && x < 0) ||
                        (this.direction == "ArrowUp" && y < 0) ||
                        (this.direction == "ArrowDown" && y == MAX_Y)
                    ) {
                        return true;
                    }
                    // 如果自己碰到了自己
                    for (let i = 0; i < this.snakeArr.length; i++) {
                        if (
                            this.snakeArr[i].x == x &&
                            this.snakeArr[i].y == y
                        ) {
                            return true;
                        }
                    }
                    return false;
                },
                gameOver(x, y) {
                    this.gameStatus.isEnd = true;
                    clearInterval(this.timer);
                    alert("游戏结束!");
                },
                autoMove() {
                    return setInterval(() => {
                        switch (this.direction) {
                            case "ArrowRight": //方向键右
                                this.move(1, 0);
                                break;
                            case "ArrowLeft": //方向键左
                                this.move(-1, 0);
                                break;
                            case "ArrowDown": //方向键下
                                this.move(0, 1);
                                break;
                            case "ArrowUp": // 方向键上
                                this.move(0, -1);
                                break;
                        }
                    }, 200);
                },
            },
            created() {
                this.twoRandomNum();
            },
            mounted() {
                document.addEventListener("keydown", (e) => {
                    let { key } = e;
                    switch (key) {
                        case "ArrowRight": //方向键右
                            this.direction = key;
                            this.move(1, 0);
                            break;
                        case "ArrowLeft": //方向键左
                            this.direction = key;
                            this.move(-1, 0);
                            break;
                        case "ArrowDown": //方向键下
                            this.direction = key;
                            this.move(0, 1);
                            break;
                        case "ArrowUp": // 方向键上
                            this.direction = key;
                            this.move(0, -1);
                            break;
                        case "Escape":
                        case "p":
                            this.gameStatus.pause = !this.gameStatus.pause;
                            if (this.gameStatus.pause) {
                                // 暂停后保存当前移动的方向
                                this.gameStatus.pauseDirection = this.direction;
                                clearInterval(this.timer);
                            } else {
                                this.direction = this.gameStatus.pauseDirection;
                                this.timer = this.autoMove();
                            }
                    }
                });
                this.timer = this.autoMove();
            },
            components: {
                cell: Cell,
            },
        });
    </script>
</body>

</html>